package com.lizemin.power.threadPool;

import java.util.concurrent.*;

/**
 * 线程池实现 - AI版
 */
public class SimpleThreadPool {
    private final BlockingQueue<Runnable> workQueue;
    private final ThreadFactory threadFactory;
    private final int corePoolSize;
    private final int maxPoolSize;
    private final long keepAliveTime;
    private final TimeUnit timeUnit;
    private int workerCount = 0;

    public SimpleThreadPool(int corePoolSize, int maxPoolSize,
                            long keepAliveTime, TimeUnit timeUnit,
                            int queueSize, ThreadFactory threadFactory) {
        this.corePoolSize = corePoolSize;
        this.maxPoolSize = maxPoolSize;
        this.workQueue = new LinkedBlockingQueue<>(queueSize);
        this.threadFactory = threadFactory;
        this.keepAliveTime = keepAliveTime;
        this.timeUnit = timeUnit;
    }

    /**
     * 用户提交的任务
     *
     * @param task 任务
     */
    public synchronized void execute(Runnable task) {
        // 创建核心线程（如果未达核心数）
        if (workerCount < corePoolSize) {
            addWorker(task, true);
            return;
        }

        // 尝试放入队列， 如果放满了，就会返回false，也就不会return，就会执行下面的逻辑
        if (workQueue.offer(task)) {
            return;
        }

        // 创建临时线程（如果队列满且未达最大线程数）
        if (workerCount < maxPoolSize) {
            addWorker(task, false);
            return;
        }
        // 超过最大线程数，会触发拒绝策略
        // 触发拒绝策略
        throw new RejectedExecutionException("Task rejected");
    }

    private void addWorker(Runnable firstTask, boolean core) {
        // 更新当前线程总数
        workerCount++;
        // 创建线程
        Thread worker = threadFactory.newThread(() -> {
            try {
                // 执行首个任务，每次执行后都会继续往下执行，往下执行的结果是从队列中获取任务，如果队列中没有任务，则会阻塞等待，从而实现核心线程数的保活
                if (firstTask != null) {
                    firstTask.run();
                }

                // 持续获取并执行任务
                Runnable nextTask;
                while (true) { // 通过这里的死循环实现了核心线程永久保活
                    // 核心线程永久等待，非核心线程超时等待
                    nextTask = core ?
                            workQueue.take() : // 核心线程永久等待
                            workQueue.poll(keepAliveTime, timeUnit); // 非核心线程超时等待，线程如果从队列中拿不到任务就会超时退出

                    if (nextTask == null){ // 如果超时返回null,也就是临时线程会退出
                        break; // 非核心线程超时退出, 线程随之销毁
                    }
                    // 从队列中拿到了任务，则直接执行
                    nextTask.run();
                }
            } catch (InterruptedException ignored) {
            } finally {
                // 线程结束或者发生了异常，更新当前线程总数
                synchronized (this) {
                    workerCount--; // 线程结束前更新计数
                }
            }
        });
        // 启动线程
        worker.start();
    }

    // 测试用例
    public static void main(String[] args) {
        ThreadFactory factory = r -> new Thread(r, "order-");
        SimpleThreadPool pool = new SimpleThreadPool(
                2, 4, 5, TimeUnit.SECONDS, 3, factory
        );

        // 提交6个任务（触发所有逻辑路径）
        for (int i = 0; i < 6; i++) {
            final int taskId = i;
            try {
                pool.execute(() -> {
                    try {
                        System.out.println(Thread.currentThread().getName() + taskId);
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                });
            } catch (RejectedExecutionException e) {
                System.out.println("Task " + taskId + " rejected");
            }
        }
    }
}